#ifndef A6636AB8_06D2_4D05_AE49_DF652D1B4D06
#define A6636AB8_06D2_4D05_AE49_DF652D1B4D06

#include "Task.hpp"
#include "thread.hpp"

const int defaultnum = 5;

class ThreadPool
{
public:
	void Lock()
	{
		pthread_mutex_lock(&mutex);
	}
	void Unlock()
	{
		pthread_mutex_unlock(&mutex);
	}
	void wake()
	{
		pthread_cond_signal(&cond);
	}
	void Threadsleep()
	{
		pthread_cond_wait(&cond, &mutex);
	}
	bool isempty()
	{
		return tasks_.empty();
	}
	std::string Getname()
	{
		pthread_t id = pthread_self();
		for(const auto& ti : threads){
			if(ti.thread_self() == id){
				return ti.name();
			}
		}
		return "None";
	}
public:
	ThreadPool(int num = defaultnum) : threads(num,thread(handler))
	{
		pthread_mutex_init(&mutex, nullptr);
		pthread_cond_init(&cond, nullptr);
	}
	void start()
	{
		int len = threads.size();
		for(int i = 0;i < len;i++)
		{
			threads[i].run(this);
		}
	}
	static void handler(void* args)
	{
		ThreadPool * tp = static_cast<ThreadPool*>(args);
		while(true)
		{
			tp->Lock();
			while(tp->isempty())
			{
				tp->Threadsleep();
			}
			Task t = tp->pop();
			tp->Unlock();
			t();
			std::cout << "deal done , resulet:" << t.Getresult() << " thread name : " << tp->Getname() << std::endl;
			sleep(5);
		}
	}
	void Push(const Task& t)
	{
		Lock();
		tasks_.push(t);
		wake();
		Unlock();
	}
	Task pop()
	{
		Task t = tasks_.front();
		tasks_.pop();
		return t;
	}
	~ThreadPool()
	{
		pthread_mutex_destroy(&mutex);
		pthread_cond_destroy(&cond);
	}
private:
	std::vector<thread> threads;
	std::queue<Task> tasks_;

	pthread_mutex_t mutex;
	pthread_cond_t cond;
};

#endif /* A6636AB8_06D2_4D05_AE49_DF652D1B4D06 */
